home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Chess++ 3.0.1 / source / CChessDoc.cp < prev    next >
Text File  |  1993-05-26  |  12KB  |  496 lines

  1. ////////////
  2. //
  3. //    CChessDoc.cp
  4. //
  5. //    Document methods for a Chess application.
  6. //
  7. //  Copyright © 1993 Steven J. Bushell. All rights reserved.
  8. //
  9. ////////////
  10.  
  11. #include <Global.h>
  12. #include <Commands.h>
  13. #include <CBartender.h>
  14. #include <CDataFile.h>
  15. #include <CDecorator.h>
  16. #include <CDesktop.h>
  17. #include <CError.h>
  18. #include <CPanorama.h>
  19. #include <CScrollPane.h>
  20. #include "CChessDoc.h"
  21. #include <TBUtilities.h>
  22. #include <CWindow.h>
  23. #include <Packages.h>
  24.  
  25. #include "CBrain.h"
  26. #include "ChessCommands.h"
  27. #include "CChessOptionsDialog.h"
  28.  
  29. #define    WINDChess        500        /* Resource ID for WIND template */
  30.  
  31. extern    CApplication *gApplication;    /* The application */
  32. extern    CBartender    *gBartender;    /* The menu handling object */
  33. extern    CDecorator    *gDecorator;    /* Window dressing object    */
  34. extern    CDesktop    *gDesktop;        /* The enclosure for all windows */
  35. extern    CBureaucrat    *gGopher;        /* The current boss in the chain of command */
  36. extern    OSType        gSignature;        /* The application's signature */
  37. extern    CError        *gError;        /* The global error handler */
  38. extern    CBrain        *gBrain;
  39.  
  40. void                DoAboutChessBox(void);
  41.  
  42. /***
  43.  * IChessDoc
  44.  *
  45.  *    This is your document's initialization method.
  46.  *    If your document has its own instance variables, initialize
  47.  *    them here.
  48.  *
  49.  *    The least you need to do is invoke the default method.
  50.  *
  51.  ***/
  52.  
  53.  
  54. void CChessDoc::IChessDoc(CApplication *aSupervisor, Boolean printable)
  55.  
  56. {
  57.     CDocument::IDocument(aSupervisor, printable);
  58.  
  59.     // Create the global brain, your virtual opponent
  60.     gBrain = new CBrain;
  61.     gBrain->IBrain(this);
  62.  
  63.     // We initially don't have a file associated with the board
  64.     itsFile = NULL;
  65. }
  66.  
  67.  
  68. /***
  69.  * Dispose
  70.  *
  71.  *    This is your document's destruction method.
  72.  *    If you allocated memory in your initialization method
  73.  *    or opened temporary files, this is the place to release them.
  74.  *
  75.  *    Be sure to call the default method!
  76.  *
  77.  ***/
  78.  
  79. void CChessDoc::Dispose()
  80.  
  81. {
  82.     inherited::Dispose();
  83. }
  84.  
  85.  
  86. /***
  87.  * DoCommand
  88.  *
  89.  *    This is the heart of your document.
  90.  *    In this method, you handle all the commands your document
  91.  *    deals with.
  92.  *
  93.  *    Be sure to call the default method to handle the standard
  94.  *    document commands: cmdClose, cmdSave, cmdSaveAs, cmdRevert,
  95.  *    cmdPageSetup, cmdPrint, and cmdUndo. To change the way these
  96.  *    commands are handled, override the appropriate methods instead
  97.  *    of handling them here.
  98.  *
  99.  ***/
  100.  
  101. void CChessDoc::DoCommand(long theCommand)
  102.  
  103. {
  104.     switch (theCommand) {
  105.  
  106.         case cmdSwapPlayers:
  107.             gBrain->abortMove = true;
  108.             SwapPlayers();
  109.             break;
  110.         case cmdStopThinking:
  111.             itsMainPane->BecomeGopher(true);
  112.             gBrain->isThinking = false;
  113.             break;
  114.         case cmdOptions:
  115.             DoChessOptionsDialog();
  116.             break;
  117.         default:
  118.             inherited::DoCommand(theCommand);
  119.             break;
  120.     }
  121. }
  122.  
  123.  
  124. /***
  125.  * UpdateMenus
  126.  *
  127.  *  In this method you can enable menu commands that apply when
  128.  *  your document is active.
  129.  *
  130.  *  Be sure to call the inherited method to get the default behavior.
  131.  *  The inherited method enables these commands: cmdClose, cmdSaveAs,
  132.  *  cmdSave, cmdRevert, cmdPageSetup, cmdPrint, cmdUndo.
  133.  *
  134. ***/
  135.  
  136.  void CChessDoc::UpdateMenus()
  137.  
  138.  {
  139.     inherited::UpdateMenus();
  140.     
  141.     // If a chess board is already open, we don't want to 
  142.     // be able to open or create a new one
  143.     gBartender->DisableCmd(cmdNew);
  144.     gBartender->DisableCmd(cmdOpen);
  145.     
  146.     gBartender->EnableCmd(cmdOptions);
  147. }
  148.  
  149.  
  150. /***
  151.  * NewFile
  152.  *
  153.  *    When the user chooses New from the File menu, the CreateDocument()
  154.  *    method in your Application class will send a newly created document
  155.  *    this message. This method needs to create a new window, ready to
  156.  *    work on a new document.
  157.  *
  158.  *    Since this method and the OpenFile() method share the code for creating
  159.  *    the window, you should use an auxiliary window-building method.
  160.  *
  161.  ***/
  162. void CChessDoc::NewFile(void)
  163.  
  164. {    
  165.     Str255  wTitle;     /* Window title string.         */
  166.     short   wCount;     /* Index number of new window.  */
  167.     Str255  wNumber;    /* Index number as a string.    */
  168.     
  169.         /**
  170.          **    BuildWindow() is the method that
  171.          **    does the work of creating a window.
  172.          ** Its parameter should be the data that
  173.          **    you want to display in the window.
  174.          **    Since this is a new window, there's nothing
  175.          **    to display.
  176.          **
  177.          **/
  178.  
  179.     BuildWindow(NULL);
  180.     
  181.         /**
  182.          ** Append an index number to the
  183.          ** default name of the window.
  184.          **/
  185.  
  186.     itsWindow->SetTitle("\pChess++");
  187.  
  188.         /**
  189.          **    Send the window a Select() message to make
  190.          **    it the active window.
  191.          **/
  192.     
  193.     itsWindow->Select();
  194. }
  195.  
  196.  
  197. /***
  198.  * OpenFile
  199.  *
  200.  *    When the user chooses Open… from the File menu, the OpenDocument()
  201.  *    method in your Application class will let the user choose a file
  202.  *    and then send a newly created document this message. The information
  203.  *    about the file is in the SFReply record.
  204.  *
  205.  *    In this method, you need to open the file and display its contents
  206.  *    in a window. This method uses the auxiliary window-building method.
  207.  *
  208.  ***/
  209.  
  210. void CChessDoc::OpenFile(SFReply *macSFReply)
  211.  
  212. {
  213.     CDataFile    *theFile;
  214.     Handle        theData = NULL;
  215.     Str63        theName;
  216.     OSErr        theError;
  217.     
  218.     TRY
  219.     {
  220.     
  221.             /**
  222.              ** Create a file and send it a SFSpecify()
  223.              **    message to set up the name, volume, and
  224.              **    directory.
  225.              **
  226.              **/
  227.     
  228.         theFile = new(CDataFile);
  229.         theFile->IDataFile();
  230.         theFile->SFSpecify(macSFReply);
  231.         
  232.             /**
  233.              **    Be sure to set the instance variable
  234.              **    so other methods can use the file if they
  235.              **    need to. This is especially important if
  236.              **    you leave the file open in this method.
  237.              **    If you close the file after reading it, you
  238.              **    should be sure to set itsFile to NULL.
  239.              **
  240.              **/
  241.     
  242.         itsFile = theFile;
  243.     
  244.             /**
  245.              **    Send the file an Open() message to
  246.              **    open it. You can use the ReadSome() or
  247.              **    ReadAll() methods to get the contents of the file.
  248.              **
  249.              **/
  250.     
  251.         theFile->Open(fsRdWrPerm);
  252.         
  253.             /**
  254.              **    Make sure that the memory request to read
  255.              **    the data from the file doesn't use up any
  256.              **    of our rainy day fund and that the GrowMemory()
  257.              **    method (in the application) knows that it's OK
  258.              **    if we couldn't get enough memory.
  259.              **
  260.              **/
  261.     
  262.     
  263.         theData = theFile->ReadAll();     /* ReadAll() creates the handle */
  264.         
  265.      
  266.         
  267.         
  268.         BuildWindow(theData);
  269.     
  270.             /**
  271.              **    In your application, you'll probably store
  272.              **    the data in some form as an instance variable
  273.              **    in your document class. For this example, there's
  274.              **    no need to save it, so we'll get rid of it.
  275.              **
  276.              **/
  277.     
  278.         DisposHandle(theData);
  279.         theData = NULL;
  280.     
  281.             /**
  282.              **    In this implementation, we leave the file
  283.              **    open. You might want to close it after
  284.              **    you've read in all the data.
  285.              **
  286.              **/
  287.     
  288.         itsFile->GetName(theName);
  289.         itsWindow->SetTitle(theName);
  290.         itsWindow->Select();            /* Don't forget to make the window active */
  291.     }
  292.     
  293.     CATCH
  294.     {
  295.         /*
  296.          * This exception handler will be executed if an exception occurs
  297.          * anywhere within the scope of the TRY block above.
  298.          * You should perform any cleanup of things that won't be needed
  299.          * since the document could not be opened. By convention,
  300.          * the creator of an object is responsible for sending it
  301.          * the Dispose message. This means that we should only dispose
  302.          * of things that would not be taken care of in Dispose.
  303.          * In this case, we just make sure that the Handle theData
  304.          * has been disposed of. The exception will propagate up to
  305.          * CApplications's exception handler, which handles displaying
  306.          * an error alert.
  307.          */
  308.          
  309.          if (theData) DisposHandle( theData);
  310.          
  311.     }
  312.     ENDTRY;
  313. }
  314.  
  315.  
  316.  
  317. /***
  318.  * BuildWindow
  319.  *
  320.  *    This is the auxiliary window-building method that the
  321.  *    NewFile() and OpenFile() methods use to create a window.
  322.  *
  323.  *    In this implementation, the argument is the data to display.
  324.  *
  325.  ***/
  326.  
  327. void CChessDoc::BuildWindow (Handle theData)
  328.  
  329. {
  330.     CPane        *thePane;
  331.     CChessPane    *theMainPane;
  332.     Rect    tempRect;
  333.     
  334.     itsWindow = new(CWindow);
  335.     itsWindow->IWindow(WINDChess, FALSE, gDesktop, this);
  336.     itsWindow->ChangeSize(256,256);
  337.  
  338.     SetRect(&tempRect,256,256,256,256);
  339.     itsWindow->SetSizeRect(&tempRect);
  340.  
  341.     theMainPane = new(CChessPane);
  342.     theMainPane->IChessPane(itsWindow, this, 0, 0, 0, 0,
  343.                             sizELASTIC, sizELASTIC);
  344.     itsMainPane = theMainPane;
  345.     itsGopher = theMainPane;
  346.  
  347.     theMainPane->FitToEnclosure(TRUE, TRUE);
  348. }
  349.  
  350.  
  351. /***
  352.  * DoSave
  353.  *
  354.  *    This method handles what happens when the user chooses Save from the
  355.  *    File menu. This method should return TRUE if the file save was successful.
  356.  *    If there is no file associated with the document, you should send a
  357.  *    DoSaveFileAs() message.
  358.  *
  359.  ***/
  360.  
  361. Boolean CChessDoc::DoSave(void)
  362.  
  363. {
  364.         /**
  365.          **    If you closed your file in your NewFile() method,
  366.          **    you'll need a different way than this to determine
  367.          **    if there's a file associated with your document.
  368.          **
  369.          **/
  370.  
  371.     if (itsFile == NULL)
  372.         return(DoSaveFileAs());
  373.     else {
  374.             
  375.         /**
  376.          **    In your application, this is where you'd
  377.          **    write out your file. if you left it open,
  378.          **    send the WriteSome() or WriteAll() mesages
  379.          **    to itsFile.
  380.          **
  381.          **/
  382.             
  383.         dirty = FALSE;                    /* Document is no longer dirty        */
  384.         gBartender->DisableCmd(cmdSave);
  385.         return(TRUE);                    /* Save was successful                */
  386.     }
  387. }
  388.  
  389.  
  390. /***
  391.  * DoSaveAs
  392.  *
  393.  *    This method handles what happens when the user chooses Save As… from
  394.  *    File menu. The default DoCommand() method for documents sends a DoSaveFileAs()
  395.  *    message which displays a standard put file dialog and sends this message.
  396.  *    The SFReply record contains all the information about the file you're about
  397.  *    to create.
  398.  *
  399.  ***/
  400.  
  401. Boolean CChessDoc::DoSaveAs(SFReply *macSFReply)
  402.  
  403. {
  404.         /**
  405.          **    If there's a file associated with this document
  406.          **    already, close it. The Dispose() method for files
  407.          **    sends a Close() message to the file before releasing
  408.          **    its memory.
  409.          **
  410.          **/
  411.          
  412.     if (itsFile != NULL)
  413.         itsFile->Dispose();
  414.  
  415.  
  416.         /**
  417.          **    Create a new file, and then save it normally.
  418.          **
  419.          **/
  420.  
  421.     itsFile = new(CDataFile);
  422.     ((CDataFile *)itsFile)->IDataFile();
  423.     itsFile->SFSpecify(macSFReply);
  424.     itsFile->CreateNew(gSignature, 'TEXT');
  425.     itsFile->Open(fsRdWrPerm);
  426.     
  427.     itsWindow->SetTitle(macSFReply->fName);
  428.  
  429.     return( DoSave() );
  430. }
  431.  
  432.  
  433. /***
  434.  * DoRevert
  435.  *
  436.  *    If your application supports the Revert command, this method
  437.  *    should close the current file (without writing anything out)
  438.  *    and read the last saved version of the file.
  439.  *
  440.  ***/
  441.  
  442. void CChessDoc::DoRevert(void)
  443.  
  444. {
  445. }
  446.  
  447. void CChessDoc::SwapPlayers(void)
  448. {
  449.     CChessBoard *itsChessBoard = ((CChessPane *)itsMainPane)->itsChessBoard;
  450.  
  451.     if (gBrain->isBrainsMove)
  452.     {
  453.         gBrain->isBrainsMove = false;
  454.         gBrain->isThinking = false;
  455.     }
  456.     
  457.     itsChessBoard->myColor = itsChessBoard->theOtherPlayersColor;
  458.     if (itsChessBoard->myColor == White)
  459.         itsChessBoard->theOtherPlayersColor = Black;
  460.     else
  461.         itsChessBoard->theOtherPlayersColor = White;
  462. }
  463.  
  464.  
  465. void CChessDoc::DoChessOptionsDialog(void)
  466. {
  467.     CChessOptionsDialog *theOptionsDialog;
  468.     
  469.     theOptionsDialog = new CChessOptionsDialog;
  470.     ParamText("\pSteven Bushell","\pSteven Bushell",NULL,NULL);
  471.     theOptionsDialog->IChessOptionsDialog(this);
  472.     theOptionsDialog->DoChessOptionsDialog();
  473.  
  474.     theOptionsDialog->Dispose();
  475. }
  476.  
  477.  
  478. void CChessDoc::ProviderChanged( CCollaborator *aProvider, long reason, void* info)
  479. {
  480.     if (member( aProvider, CBureaucrat) && (reason == bureaucratIsGopher))
  481.     {    
  482.         if (member( aProvider, CBrain))
  483.         {    // If the Brain is thinking, we don't want the user
  484.             // interrupting with anything but StopThinking
  485.             gBartender->DisableMenu(MENUfile);
  486.             gBartender->DisableMenu(MENUedit); 
  487.         }
  488.         else if (member( aProvider, CChessPane))
  489.         {
  490.             gBartender->EnableMenu(MENUfile);
  491.             gBartender->EnableMenu(MENUedit);
  492.         }
  493.     }
  494.     inherited::ProviderChanged( aProvider, reason, info);
  495.  
  496. }    /* CDirector::ProviderChanged */